package com.kb.service.impl.gc;


import cn.iocoder.yudao.module.system.api.category.CategoryApi;
import cn.iocoder.yudao.module.system.api.category.dto.CategoryRespDTO;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.kb.domain.SplitFieldConfigDO;
import com.kb.domain.gc.CategoryAggregationFieldDO;
import com.kb.domain.gc.CategoryRespVO;
import com.kb.entity.ComponentData;
import com.kb.entity.ComponentDataHeaderField;
import com.kb.entity.Header;
import com.kb.mapper.es.CategoryAggregationFieldMapper;
import com.kb.mapper.es.SplitFieldConfigMapper;
import com.kb.service.gc.AggregationFieldService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 国创工软
 */

@Service
@Slf4j
public class AggregationFieldServiceImpl implements AggregationFieldService {

    @Resource
    private CategoryAggregationFieldMapper categoryAggregationFieldMapper;

    @Resource
    private CategoryApi categoryApi;


    @Resource
    private SplitFieldConfigMapper splitFieldConfigMapper;

    @Override
    public void handleAggregationField(List<ComponentData> dataDOList, List<Header> dataHeaderDOList,
                                       List<ComponentDataHeaderField> dataHeaderFieldList) {
        Map<Long, List<Header>> idHeaderMap = dataHeaderDOList.stream().collect(Collectors.
                groupingBy(Header::getId));
        Map<Long, List<ComponentDataHeaderField>> setIdFieldMap = dataHeaderFieldList.stream().collect(Collectors.
                groupingBy(ComponentDataHeaderField::getSetId));
        List<CategoryAggregationFieldDO> categoryAggregationFieldList = new ArrayList<>();
        for (ComponentData componentDataDO : dataDOList) {
            Map keyFieldMap = JSONObject.parseObject(componentDataDO.getTechTemplateFields(), Map.class);
            Long setId = componentDataDO.getSetId();
            if (Objects.isNull(idHeaderMap.get(setId))) {
                continue;
            }
            //一个setId用一个表头
            Header dataHeader = idHeaderMap.get(setId).get(0);
            //产品挂靠的分类id。可能二级，也可能三级
            Long platformCategoryId = dataHeader.getPlatformCategoryId();
            CategoryRespVO parentTree = getParentTree(platformCategoryId);
            //一级
            Long firstCategoryId = Objects.nonNull(parentTree) ? parentTree.getId() : null;
            //二级
            List<CategoryRespVO> secondCategory = Objects.nonNull(parentTree) ? parentTree.getChildren() : null;
            Long secondCategoryId = getChildrenId(secondCategory);
            //三级
            List<CategoryRespVO> thirdCategory = Objects.nonNull(secondCategory) ? secondCategory.get(0).getChildren() : null;
            Long thirdCategoryId = getChildrenId(thirdCategory);
            List<CategoryAggregationFieldDO> aggregationFieldList =
                    categoryAggregationFieldMapper.selectListByType(firstCategoryId, secondCategoryId, thirdCategoryId, 2);
            Map<String, List<CategoryAggregationFieldDO>> fieldNameMap = aggregationFieldList.stream().collect(Collectors.
                    groupingBy(CategoryAggregationFieldDO::getAggregationFieldName));
            //产品属性
            List<ComponentDataHeaderField> headerFieldList = setIdFieldMap.get(setId);
            Map<String, Object> aggFieldMap = assembleAggregationField(headerFieldList, keyFieldMap);
            for (Map.Entry<String, Object> stringObjectEntry : aggFieldMap.entrySet()) {
                if (fieldNameMap.containsKey(stringObjectEntry.getKey())) {
                    continue;
                }
                CategoryAggregationFieldDO categoryAggregationFieldDO = new CategoryAggregationFieldDO();
                categoryAggregationFieldDO.setId(IdWorker.getId() );
                categoryAggregationFieldDO.setFirstCategoryId(firstCategoryId);
                categoryAggregationFieldDO.setSecondCategoryId(secondCategoryId);
                categoryAggregationFieldDO.setThirdCategoryId(thirdCategoryId);
                categoryAggregationFieldDO.setAggregationType(2);
                categoryAggregationFieldDO.setAggregationFieldName(stringObjectEntry.getKey());
                categoryAggregationFieldDO.setCreator(String.valueOf(IdWorker.getId() ));
                categoryAggregationFieldDO.setUpdater(String.valueOf(IdWorker.getId() ));
                categoryAggregationFieldList.add(categoryAggregationFieldDO);
            }
        }
        if (CollectionUtils.isNotEmpty(categoryAggregationFieldList)) {
            categoryAggregationFieldList = distinctByKey(categoryAggregationFieldList);
            for (CategoryAggregationFieldDO categoryAggregationFieldDO : categoryAggregationFieldList) {
                categoryAggregationFieldMapper.insert(categoryAggregationFieldDO);
            }
        }
    }


    private Map<String, Object> assembleAggregationField(List<ComponentDataHeaderField> headerFieldList, Map keyFieldMap) {
        List<SplitFieldConfigDO> splitFieldConfigList = splitFieldConfigMapper.selectList(null);
        Map<String, Object> similarityFieldMap = new HashMap<>();
        List<String> splitFieldNameList = splitFieldConfigList.stream().map(SplitFieldConfigDO::getFieldName).collect(Collectors.toList());
        //字段值map
        for (ComponentDataHeaderField headField : headerFieldList) {
            String fieldNameNew = handleFieldName(headField.getFieldName());
            String fieldValue = keyFieldMap.get(headField.getFieldKey()).toString();
            String fieldValueNew = fieldValue.replaceAll(" ", "").replaceAll(",", "");
            //需要拆的字段
            if (CollectionUtils.isNotEmpty(splitFieldNameList) && (splitFieldNameList.contains(fieldNameNew)
                    && StringUtils.isNotEmpty(fieldValueNew))) {
                splitFieldByValue(fieldNameNew, fieldValueNew, similarityFieldMap);
            } else {
                similarityFieldMap.put(fieldNameNew, fieldValueNew);
            }
        }
        return similarityFieldMap;
    }

    private void splitFieldByValue(String fieldName, String fieldValue, Map<String, Object> similarityFieldMap) {
        if (fieldValue.contains("~")) {
            String[] split = fieldValue.split("~");
            String minAggKey = String.format("最小%s", fieldName);
            similarityFieldMap.put(minAggKey, split[0].trim());
            String maxAggKey = String.format("最大%s", fieldName);
            similarityFieldMap.put(maxAggKey, split[1].trim());
        } else if (fieldValue.contains("±")) {
            String replace = fieldValue.replace("±", "");
            String leftValue = "-" + replace;
            String right = "+" + replace;
            String minAggKey = String.format("最小%s", fieldName);
            similarityFieldMap.put(minAggKey, leftValue.trim());
            String maxAggKey = String.format("最大%s", fieldName);
            similarityFieldMap.put(maxAggKey, right.trim());
        } else if (fieldValue.contains(",") || fieldValue.contains("，")) {
            String key = String.format("%s", fieldName);
            String[] split;
            if (fieldValue.contains(",")) {
                split = fieldValue.split(",");
                similarityFieldMap.put(key, split);
            }
            if (fieldValue.contains("，")) {
                split = fieldValue.split("，");
                similarityFieldMap.put(key, split);
            }
        }
    }

    private String handleFieldName(String fieldName) {
        if (StringUtils.isNotEmpty(fieldName)) {
            return fieldName.replaceAll("\\s*", "").replaceAll("\\n< >", "")
                    .replaceAll("<>","").replaceAll("< >","")
                    .replace("*", "").replaceAll(" ", "").replaceAll("\\u00A0", "");
        } else {
            return fieldName;
        }
    }


    private List<CategoryAggregationFieldDO> distinctByKey(List<CategoryAggregationFieldDO> agregationFieldList) {
        List<CategoryAggregationFieldDO> collect = agregationFieldList.stream().filter(c ->
                Objects.nonNull(c.getThirdCategoryId())).collect(Collectors.toList());
        List<CategoryAggregationFieldDO> list1 = collect.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                                new TreeSet<>(
                                        Comparator.comparing(CategoryAggregationFieldDO::getFirstCategoryId)
                                                .thenComparing(CategoryAggregationFieldDO::getSecondCategoryId)
                                                .thenComparing(CategoryAggregationFieldDO::getThirdCategoryId)
                                                .thenComparing(CategoryAggregationFieldDO::getAggregationFieldName)
                                                .thenComparing(CategoryAggregationFieldDO::getAggregationType))),
                        ArrayList::new));
        List<CategoryAggregationFieldDO> collect1 = agregationFieldList.stream().filter(c ->
                Objects.isNull(c.getThirdCategoryId())).collect(Collectors.toList());
        List<CategoryAggregationFieldDO> list2 = collect1.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                                new TreeSet<>(
                                        Comparator.comparing(CategoryAggregationFieldDO::getFirstCategoryId)
                                                .thenComparing(CategoryAggregationFieldDO::getSecondCategoryId)
                                                .thenComparing(CategoryAggregationFieldDO::getAggregationFieldName)
                                                .thenComparing(CategoryAggregationFieldDO::getAggregationType))),
                        ArrayList::new));
        list2.addAll(list1);
        return list2;
    }

    public CategoryRespVO getParentTree(Long categoryId) {
        CategoryRespDTO categoryRespDTO = categoryApi.getById(categoryId).getCheckedData();
        CategoryRespVO categoryRespVO = new CategoryRespVO();
        if (categoryRespDTO != null) {
            BeanUtils.copyProperties(categoryRespDTO, categoryRespVO);
            if (categoryRespDTO.getParentId() != 0L) {
                return getParent(categoryRespVO, categoryRespDTO.getParentId());
            }
        }
        return categoryRespVO;
    }

    private CategoryRespVO getParent(CategoryRespVO categoryRespVO, Long parentId) {
        CategoryRespDTO categoryRespDTO = categoryApi.getByParentId(parentId).getCheckedData();
        CategoryRespVO parentCategoryRespVO = new CategoryRespVO();
        BeanUtils.copyProperties(categoryRespDTO, parentCategoryRespVO);
        if (categoryRespDTO != null) {
            List<CategoryRespVO> categoryRespVOList = new ArrayList<>();
            categoryRespVOList.add(categoryRespVO);
            parentCategoryRespVO.setChildren(categoryRespVOList);
            if (Objects.nonNull(categoryRespDTO.getParentId()) && categoryRespDTO.getParentId() != 0L) {
                return getParent(parentCategoryRespVO, categoryRespDTO.getParentId());
            }
        }
        return parentCategoryRespVO;
    }

    private Long getChildrenId(List<CategoryRespVO> children) {
        if (CollectionUtils.isNotEmpty(children)) {
            CategoryRespVO categoryRespVO = children.get(0);
            return categoryRespVO.getId();
        } else {
            return null;
        }
    }
}
